package com.spic.business.utils;

/**
 * @author : 赵祥
 * create at:  2022/8/26  14:16
 * @Description :
 **/

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.spic.common.core.exception.ServiceException;
import lombok.Getter;
import org.apache.commons.compress.utils.Sets;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilterInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Set;

@Component
public class ImagemarkUtils {
    @Value("${office.directory:/tmp}")
    private String outPutDirectory;

    /**
     * 给图像添加文字水印
     *
     * @param targetImgPath  目标文件地址
     * @param text           水印内容
     * @param color          水印文字颜色
     * @param alpha          水印透明度
     * @param positionWidth  水印横向位置
     * @param positionHeight 水印纵向位置
     * @param degree         水印图片旋转角度
     * @param location       水印的位置，左上角、右上角、左下角、右下角、居中
     */
    public File markImage(InputStream srcImgInputStream,
                          String targetImgPath,
                          String text,
                          Font font,
                          Color color,
                          float alpha,
                          int positionWidth,
                          int positionHeight,
                          Integer degree,
                          String location) {
        try {
            // 1、读取源图片
            Image srcImg = ImageIO.read(srcImgInputStream);
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            BufferedImage buffImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);

            // 2、得到画笔对象
            Graphics2D g = buffImg.createGraphics();
            // 3、设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(srcImg.getScaledInstance(srcImgWidth, srcImgHeight, Image.SCALE_SMOOTH), 0, 0, null);
            // 4、设置水印旋转
            if (null != degree) {
                g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
            }
            // 5、设置水印文字颜色
            g.setColor(color);
            // 6、设置水印文字Font
            g.setFont(font);
            // 7、设置水印文字透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            // 8、水印图片的位置
            int x = 0, y = 0;
            int fontSize = font.getSize();
            if (StringUtils.equals(location, "left-top")) {
                x = fontSize / 2;
                y = fontSize;
            } else if (StringUtils.equals(location, "right-top")) {
                x = srcImgWidth - getWatermarkLength(text, g) - 25;
                y = fontSize;
            } else if (StringUtils.equals(location, "left-bottom")) {
                x += 25;
                y = buffImg.getHeight() - fontSize;
            } else if (StringUtils.equals(location, "right-bottom")) {
                x = srcImgWidth - getWatermarkLength(text, g) - 25;
                y = srcImgHeight - fontSize;
            } else if (StringUtils.equals(location, "center")) {
                x = (srcImgWidth - getWatermarkLength(text, g)) / 2;
                y = srcImgHeight / 2;
            } else {
                //自定义位置
                x = positionWidth;
                y = positionHeight;
            }

            //绘制文字
            int oneLineSize = (srcImgWidth - fontSize) / fontSize;
            Iterable<String> chunks = Splitter.fixedLength(oneLineSize).split(text);
            ArrayList<String> markList = Lists.newArrayList(chunks);

            for (int i = 0; i < markList.size(); i++) {
                // 9、第一参数->设置的内容，后面两个参数->文字在图片上的坐标位置(x,y)
                g.drawString(markList.get(i), 5, y + i * fontSize);
            }
            // 10、释放资源
            g.dispose();
            // 11、生成图片
            File outputFile = new File(targetImgPath);
            File fileParent = outputFile.getParentFile();
            if (!fileParent.exists()) {
                outputFile.mkdirs();
            }
            if (!outputFile.exists()) {
                outputFile.createNewFile();
            }
            ImageIO.write(buffImg, "jpg", outputFile);
            return outputFile;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 计算填充的水印长度
     *
     * @param text
     * @param g
     * @return
     */
    private static int getWatermarkLength(String text, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(text.toCharArray(), 0, text.length());
    }

    /**
     * 根据图片的路径，把图片转化为流
     */
    public static InputStream getImageStream(String address) throws Exception {
        URL url = new URL(address);
        // 打开连接
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        // 输入流;
        InputStream is = con.getInputStream();
        return is;
    }

    public File markImage(String url, String text, FilterInputStream inputStream) {
        Color color = Color.red; //水印文字颜色
        Font font = new Font("宋体", Font.BOLD, 50); //水印文字字体
        float alpha = 1.0f; //水印透明度
        int positionWidth = 0; //水印横向位置坐标
        int positionHeight = 50; //水印纵向位置坐标
        Integer degree = null; //水印旋转角度
        String location = "left-top"; //水印的位置

        FileInfo srcFile = new FileInfo().initByPath(url);
        String imgFileName = srcFile.getFilename() + "." + "jpg";
        String targetImgPath = outPutDirectory + File.separator + imgFileName;
        return markImage(inputStream, targetImgPath, text, font, color, alpha, positionWidth, positionHeight, degree, location);
    }

    @Getter
    static class FileInfo {
        private String filename;//名称  eg: index
        private String suffix;//后缀 eg:html
        private String fullPathName;//全路径 eg: /usr/local/share/html/index.html
        private String fileFullName; //eg: index.html

        //可转换的后缀类型
        static Set<String> LEGAL_SUFFIX = Sets.newHashSet(
                "pdf", "swf", "html", "odt", "ott", "fodt", "sxw",
                "doc", "docx", "rtf", "wpd", "txt", "ods",
                "ots", "fods", "sxc", "xls", "xlsx", "csv",
                "tsv", "odp", "otp", "fodp", "sxi", "ppt",
                "pptx", "odg", "otg", "fodg", "svg", "png",
                "jpg", "tif", "gif");

        FileInfo initBySuffix(String suffix) {
            this.suffix = suffix;
            checkSuffix();
            return this;
        }

        FileInfo initByPath(String pathName) {
            this.fullPathName = pathName;
            String pathStandardName = getStandardPath(pathName);
            String[] path = pathStandardName.split("/");
            this.fileFullName = path[path.length - 1];
            int dot = fileFullName.indexOf(".");
            this.filename = fileFullName.substring(0, dot);
            this.suffix = fileFullName.substring(dot + 1).toLowerCase();
//            checkExists();
            checkSuffix();
            return this;
        }

        FileInfo initByFileName(String fileFullName) {
            this.fileFullName = fileFullName;
            int dot = fileFullName.indexOf(".");
            this.filename = fileFullName.substring(0, dot);
            this.suffix = fileFullName.substring(dot + 1).toLowerCase();
            checkSuffix();
            return this;
        }

        //替换windos分隔符
        String getStandardPath(String path) {
            return path.replace("\\", "/");
        }

        //检查文件格式的合法性
        void checkSuffix() {
            boolean isLegal = LEGAL_SUFFIX.contains(this.getSuffix());
            if (!isLegal) throw new ServiceException(getFileFullName() + "的文件格式不支持预览");
        }

        //检查文件是否存在
        void checkExists() {
            boolean isExists = new File(getFullPathName()).exists();
            if (!isExists) throw new ServiceException("未找到要预览的文件“" + getFilename() + "”，请检查文件路径是否正确");
        }
    }
}
